package com.cuixichang.minimalism.core.mybatis.utils;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.cuixichang.minimalism.core.mybatis.base.BasePo;
import com.cuixichang.minimalism.core.mybatis.cnstants.BaseConfigParam;
import com.cuixichang.minimalism.core.mybatis.core.*;
import org.apache.ibatis.annotations.Mapper;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CodeGeneratorUtil {

    private DataSourceConfig.Builder builder;

    public CodeGeneratorUtil(DataSourceConfig.Builder builder){
        this.builder = builder;
    }

    public void execute(String tableName, String author) {
        DataSourceConfig.Builder databaseBuilder = builder;
        FastAutoGenerator.create(databaseBuilder)
                .globalConfig(builder -> globalConfig(builder,author,finalProjectPath()))
                .packageConfig(builder -> packageConfig(builder))
                .templateConfig(builder -> templateConfig(builder))
                .injectionConfig(builder -> injectionConfig(builder))
                .strategyConfig(builder -> strategyConfig(builder,tableName))
                .templateEngine(new CustomVelocityTemplateEngine())
                .execute();
    }

    private void globalConfig(GlobalConfig.Builder builder, String author, String finalProjectPath){
        builder.author(author) // 设置作者
                .enableSwagger() // 开启 swagger 模式
                .dateType(DateType.TIME_PACK)// 时间策略
                .commentDate(BaseConfigParam.commentDate)// 格式化时间格式
                .disableOpenDir() //禁止打开输出目录
                .outputDir(finalProjectPath + BaseConfigParam.outputDir); // 指定输出目录
    }
    private static void packageConfig(PackageConfig.Builder builder){
        builder.parent(BaseConfigParam.ROOT_PATH) // 设置父包名
                .moduleName(BaseConfigParam.MODULE_NAME_PATH) // 设置父包模块名
                .entity(BaseConfigParam.MODULE_PO_PATH)// 实体类包名
                .controller(BaseConfigParam.MODULE_CONTROLLER_PATH)// 控制层包名
                .mapper(BaseConfigParam.MODULE_MAPPER_PATH)// mapper层包名
                .xml(BaseConfigParam.MODULE_MAPPER_PATH)// 数据访问层xml包名
                .service(BaseConfigParam.MODULE_SERVICE_PATH)// service层包名
                .serviceImpl(BaseConfigParam.MODULE_SERVICE_PATH)// service实现类包名
        ;
    }
    private static void templateConfig(TemplateConfig.Builder builder){
        builder.mapper(BaseConfigParam.TEMPLATE_MAPPER_PATH)// mapper模板路径
                //.disable()//禁用所有模板
                //.disable(TemplateType.ENTITY)禁用指定模板
                .entity(BaseConfigParam.TEMPLATE_ENTITY_PATH) // 实体模板路径
                .controller(BaseConfigParam.TEMPLATE_CONTROLLER_PATH)// controller层模板路径
                .service(BaseConfigParam.TEMPLATE_SERVICE_PATH)// service模板路径
                .serviceImpl(BaseConfigParam.TEMPLATE_SERVICE_IMPL_PATH)// 实现类模板路径
                .entityKt(BaseConfigParam.TEMPLATE_DTO_PATH)
                .xml(BaseConfigParam.TEMPLATE_MAPPER_XML_PATH)// xml文件模板路路径
        ;
    }
    private static void injectionConfig(InjectionConfig.Builder builder){
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put(BaseConfigParam.ROOT_PATH_TAG, BaseConfigParam.ROOT_PATH.concat(StrUtil.DOT).concat(BaseConfigParam.MODULE_NAME_PATH)); //去除生成前缀
        List<CustomFile> customFiles = new ArrayList<>();
        DefaultClassDecorate decorate = new DefaultClassDecorate();
        DTOClassDecorate dtoClassDecorate = new DTOClassDecorate(decorate);
        VOClassDecorate voClassDecorate = new VOClassDecorate(dtoClassDecorate);
        RequestClassDecorate requestClassDecorate = new RequestClassDecorate(voClassDecorate);
        QueryRequestClassDecorate queryRequestClassDecorate = new QueryRequestClassDecorate(requestClassDecorate);
        PageRequestClassDecorate pageRequestClassDecorate = new PageRequestClassDecorate(queryRequestClassDecorate);
        AssemblerClassDecorate assemblerClassDecorate = new AssemblerClassDecorate(pageRequestClassDecorate);
        assemblerClassDecorate.definition(customFiles);
        builder.customMap(paramMap).customFile(customFiles);
    }
    private void strategyConfig(StrategyConfig.Builder builder, String tableName){
        builder.enableCapitalMode()// 开启全局大写命名
                .addInclude(new String[]{tableName})
                .mapperBuilder().enableFileOverride()
                .entityBuilder().enableFileOverride()
                .serviceBuilder().enableFileOverride()
                //.likeTable()模糊表匹配
                //.disableSqlFilter()禁用sql过滤:默认(不使用该方法）true
                //.enableSchema()启用schema:默认false
                .entityBuilder() // 实体策略配置
                //.disableSerialVersionUID()禁用生成SerialVersionUID：默认true
                //.enableChainModel()// 开启链式模型
                .enableLombok()// 开启lombok
                //.enableRemoveIsPrefix()// 开启 Boolean 类型字段移除 is 前缀
                .enableTableFieldAnnotation()// 开启生成实体时生成字段注解
                .addTableFills()
                .enableLombok().enableLombok()
                .naming(NamingStrategy.underline_to_camel)// 数据表映射实体命名策略：默认下划线转驼峰underline_to_camel
                .columnNaming(NamingStrategy.underline_to_camel)// 表字段映射实体属性命名规则：默认null，不指定按照naming执行
                .idType(IdType.AUTO)// 添加全局主键类型
                .formatFileName("%s")// 格式化实体名称，%s取消首字母I
                .logicDeleteColumnName(BaseConfigParam.logicDeleteColumnName)
                // .addIgnoreColumns("id","isEnable","sort","createTime","updateTime","createLoginId","updateLoginId")
                .superClass(BasePo.class)
                .build()
                .mapperBuilder()// mapper文件策略
                .mapperAnnotation(Mapper.class)// 开启mapper注解
                .enableBaseResultMap()// 启用xml文件中的BaseResultMap 生成
                .enableBaseColumnList()// 启用xml文件中的BaseColumnList
               // .cache(MybatisCacheManager.class) //设置缓存实现类
                .formatMapperFileName(BaseConfigParam.formatMapperFileName)// 格式化Dao类名称
                .formatXmlFileName(BaseConfigParam.formatMapperFileName)// 格式化xml文件名称
                .build()
                .serviceBuilder()// service文件策略
                .formatServiceFileName(BaseConfigParam.formatServiceFileName)// 格式化 service 接口文件名称
                .formatServiceImplFileName(BaseConfigParam.formatServiceImplFileName)// 格式化 service 接口文件名称
                .build()
                .controllerBuilder()// 控制层策略
                .enableHyphenStyle() //开启驼峰转连字符，默认：false
                .enableRestStyle()// 开启生成@RestController
                .enableFileOverride()
                .formatFileName(BaseConfigParam.formatFileName)// 格式化文件名称
        ;
    }

    private String finalProjectPath(){
        URL xmlpath = this.getClass().getClassLoader().getResource("");
        return xmlpath.getPath().substring(0,xmlpath.getPath().indexOf("/target/"));
    }
}
